﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Kollektiv.Extension;

namespace Kollektiv.Web.Mvc
{
    public class ControllerFactory : System.Web.Mvc.IControllerFactory
    {
        private string routeID;
        private Dictionary<string, Type> controllerTypes;
        private List<Controller> controllerInstances;

        public ControllerFactory(string routeID)
        {
            this.routeID = routeID;
            this.controllerTypes = new Dictionary<string, Type>();
            this.controllerInstances = new List<Controller>();
        }

        public System.Web.Mvc.IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
        {
            Type controllerType = this.controllerTypes.ContainsKey(controllerName) ? this.controllerTypes[controllerName] : controllerName.FindType();
            Controller controller = this.controllerInstances.Where(c => c.GetType().FullName == controllerName).FirstOrDefault();

            if (controller == null)
            {
                if (controllerType.FullName != typeof(Controller).FullName && !controllerType.IsSubclassOf(typeof(Controller)))
                    throw (new ArgumentException(string.Concat("controller <", controllerName, "> has to be of type <", typeof(Controller).FullName, ">")));

                controller = (Controller)Activator.CreateInstance(controllerType);

                controller.RouteID = this.routeID;

                this.controllerInstances.Add(controller);
            }

            ((Controller)controller).ControllerContext = new System.Web.Mvc.ControllerContext(requestContext, controller);
            return controller;
        }

        public void ReleaseController(System.Web.Mvc.IController controller)
        {
            if (controller is Controller)
            {
                if (this.controllerInstances.Contains((Controller)controller))
                {
                    controllerInstances.Remove((Controller)controller);
                }

                IDisposable disposable = controller as IDisposable;
                if (disposable != null)
                {
                    disposable.Dispose();
                }
            }
        }
    }
}
